﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2013  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Ext.h".
//-------------------------------------------------------------------

#include "GLESFrameBuffer.h"

namespace UX_STL
{
namespace GLESshell
{
	
//------------------------- GLESFrameBuffer -----------------------//
/*
=================================================
	конструктор
=================================================
*/
	GLESFrameBuffer::GLESFrameBuffer(): _uID(0)
	{
		FOR( i, _aBuffers ) {
			_aBuffers[i].eAttach = _s_IndexToAttachment( i );
		}
	}

	GLESFrameBuffer::GLESFrameBuffer(GLESFrameBuffer &cFB):
		_uID(cFB._uID), _aBuffers(cFB._aBuffers)
	{
		cFB._uID = 0;
		cFB.Destroy();
	}

/*
=================================================
	деструктор
=================================================
*/
	GLESFrameBuffer::~GLESFrameBuffer()
	{
		if ( _uID != 0 )
		{
			if ( IsBinded() )
				SMAN()->BindFramebuffer( 0 );
			
			GLOM()->DeleteFramebuffers( 1, &_uID );
			_uID = 0;
		}
	}

/*
=================================================
	удаляет буферы
=================================================
*/
	void GLESFrameBuffer::Destroy()
	{
		if ( _uID != 0 )
		{
			if ( IsBinded() )
				SMAN()->BindFramebuffer( 0 );
			
			GLOM()->DeleteFramebuffers( 1, &_uID );
			_uID = 0;
		}

		FOR( i, _aBuffers ) {
			_aBuffers[i].eTarget = gl_texture::_UNKNOWN;
			_aBuffers[i].uID	 = 0;
		}
	}

/*
=================================================
	создает кадровый буфер
=================================================
*/
	bool GLESFrameBuffer::Create()
	{
		if ( _uID != 0 )
		{
			DetachAll();
			return true;
		}

		CHECK_RETURN( GLOM()->GenFramebuffers( 1, &_uID ) );
		return true;
	}

/*
=================================================
	проверяет статус буфера
=================================================
*/
	bool GLESFrameBuffer::CheckStatus()
	{
		GLenum  status;
		GL_CALL( status = glCheckFramebufferStatus( Target() ) );
		
		switch ( status )
		{
			case GL_FRAMEBUFFER_COMPLETE :
				return true;

			case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT :
				RETURN_ERROR( "Framebuffer incomplete: Attachment is not complete" );

			case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT :
				RETURN_ERROR( "Framebuffer incomplete: No image is attached to FBO" );

			case GL_FRAMEBUFFER_UNSUPPORTED :
				RETURN_ERROR( "Unsupported by FBO implementation" );

			case EXT_multisampled_render_to_texture::GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE :
				RETURN_ERROR( "Framebuffer incomplete: Multisample" );
		};

		RETURN_ERROR( "Framebuffer: Unknow error, code: 0x" << string().FormatI( status, 16 ) );
	}

/*
=================================================
	отсоединяет все присоединенные цели рендеринга
=================================================
*/
	void GLESFrameBuffer::DetachAll()
	{
		FOR( i, _aBuffers )
		{
			if ( _aBuffers[i].eTarget == gl_texture::_UNKNOWN || _aBuffers[i].uID == 0 )
				continue;

			GL_CALL( glFramebufferTexture2D( Target(), _aBuffers[i].eAttach, gl_texture::TEXTURE_2D, 0, 0 ) );

			_aBuffers[i].uID		= 0;
			_aBuffers[i].eTarget	= gl_texture::_UNKNOWN;
		}
	}

	


//---------------------- GLESDefaultFrameBuffer -------------------//
/*
=================================================
	возвращает размер буфера необходимый для
	записи в него изображения с экрана
=================================================
*/
	bool GLESDefaultFrameBuffer::GetImageDataSize(const uvec2 &vDim, gl_pixel_format::type eFormat, gl_pixel::type eType, usize &uDataSize)
	{
		uint	u_bpp = 0;
		
		// TODO
		//if ( !GLTexFormatInfo::GetBitPerPixel( eFormat, eType, u_bpp ) )
		//	return false;

		uDataSize = u_bpp * vDim.x * vDim.y;
		return true;
	}
	
//-------------------------------------------------------------------

}	// GLESshell
}	// UX_STL
